package elitequant.util;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;

import elitequant.util.MsgEventServer.SelectorLoop;

public class TickEventServer {

    public static SelectorLoop connectionBell;

    public boolean isReadBellRunning = false;
    
    private Random random = new Random();

    public static void main(String[] args) throws IOException {

        new TickEventServer().startServer();

    }

    // 启动服务器

    public void startServer() throws IOException {

        // 准备好一个闹钟.当有链接进来的时候响.

        connectionBell = new SelectorLoop();

        // 开启一个server channel来监听

        ServerSocketChannel ssc = ServerSocketChannel.open();

        // 开启非阻塞模式

        ssc.configureBlocking(false);

        ServerSocket socket = ssc.socket();

        socket.bind(new InetSocketAddress("localhost", 55555));

        // 给闹钟规定好要监听报告的事件,这个闹钟只监听新连接事件.

        ssc.register(connectionBell.getSelector(), SelectionKey.OP_ACCEPT);

        new Thread(connectionBell).start();

    }

    // Selector轮询线程类

    public class SelectorLoop implements Runnable {

        private Selector selector;

        private ByteBuffer temp = ByteBuffer.allocate(1024);

        public SelectorLoop() throws IOException {

            this.selector = Selector.open();

        }

        public Selector getSelector() {

            return this.selector;

        }

        @Override

        public void run() {

            while (true) {

                try {

                    // 阻塞,只有当至少一个注册的事件发生的时候才会继续.

                    this.selector.select();

                    Set<SelectionKey> selectKeys = this.selector.selectedKeys();

                    Iterator<SelectionKey> it = selectKeys.iterator();

                    while (it.hasNext()) {

                        SelectionKey key = it.next();

                        it.remove();

                        // 处理事件. 可以用多线程来处理.

                        this.dispatch(key);

                    }

                } catch (IOException e) {

                    e.printStackTrace();

                } catch (InterruptedException e) {

                    e.printStackTrace();

                }

            }

        }

        public void dispatch(SelectionKey key)
                throws IOException, InterruptedException {

            if (key.isAcceptable()) {

                // 这是一个connection accept事件, 并且这个事件是注册在serversocketchannel上的.

                ServerSocketChannel ssc = (ServerSocketChannel) key.channel();

                // 接受一个连接.

                SocketChannel sc = ssc.accept();

                // 对新的连接的channel注册read事件. 使用readBell闹钟.

                sc.configureBlocking(false);

                while(true) {
                    String msg = String.format("SPY STK SMART|2|3|%d\0", random.nextLong());
                    sc.write(ByteBuffer.wrap(msg
                            .getBytes(Charset.forName("UTF-8"))));
                    Thread.sleep(2000);
                }


            } 

        }

    }
}
